from typing import Optional
from urllib.parse import urlencode
import requests

from .constants import BROWSER_USER_AGENT
from .models.device_authorization import DeviceAuthorization, IdentityInfo


class DeviceOperations:
    DEVICE_URL_TEMPLATE = "http://{sn}.x86localweb.onethingcloud.com"
    DEFAULT_HEADERS = {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
        "User-Agent": BROWSER_USER_AGENT
    }

    def __init__(self, da: DeviceAuthorization) -> None:
        self.sn = da.sn
        self.device_url = self.DEVICE_URL_TEMPLATE.format(sn=self.sn)
        self.session = self._create_session(da)

    def _create_session(self, da: DeviceAuthorization):
        session = requests.session()
        session.cookies.update(da.identity_info.model_dump())
        session.headers.update(self.DEFAULT_HEADERS)
        session.headers['Referer'] = self._generate_referer_url(da)
        return session

    def _generate_referer_url(self, da: DeviceAuthorization):
        params = {"expire": da.expire, "sign": da.sign}
        return self.device_url + "?" + urlencode(params)

    def _request(self, method: str, path: str, data: Optional[dict] = None):
        url = f"{self.device_url}{path}"
        return self.session.request(method, url, data=data)

    def _get(self, path: str):
        return self._request('GET', path)

    def _post(self, path: str, data: Optional[dict] = None):
        return self._request('POST', path, data)

    def fetch_pppoe_network_info(self):
        response = self._get("/v1.0/devices/multpppoe/status")
        response.raise_for_status()
        return response.json()

    def fetch_promised_bandwidth(self):
        response = self._post("/v1.0/devices/export_bandwidth/get")
        response.raise_for_status()
        return response.json()

    def fetch_business_type(self):
        response = self._get("/v1.0/recruitment/result_info")
        response.raise_for_status()
        return response.json()

    def fetch_device_info(self):
        response = self._get("/v1.0/devices/get_info")
        response.raise_for_status()
        return response.json()

    def fetch_device_status(self):
        response = self._get("/v1.0/devices/status")
        response.raise_for_status()
        return response.json()
